/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fb.vis.login;

import com.restfb.DefaultFacebookClient;
import com.restfb.FacebookClient;
import fb.vis.types.CurrentUser;
import fb.vis.types.Friend;
import fb.vis.types.FriendList;
import fb.vis.types.Friendship;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;

@WebServlet(name = "HomePage", urlPatterns = {HomePage.URL_MAPPING})
public class HomePage extends HttpServlet {

    public static final String URL_MAPPING = "/HomePage";
    public static final String FRIENDS_JSP = "friends.jsp";
    
    private int graphWidth = 1024;
    private int graphHeight = 5000;
    
    private String uidFriend = null;

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("HomePage get");
        showFriends(request, response);
        
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.println("HomePage post");
        showFriends(request, response);
        
    }

    private void showFriends(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String token = (String) request.getSession().getAttribute("token");
        // kdyz nemame token, zpet na loginManager
        if (token == null || token.isEmpty()){
            response.sendRedirect(request.getContextPath()+"/LoginManager");
            return;
        }
        FacebookClient fbClient = new DefaultFacebookClient(token);
        
        // podminka pohlavi do dotazu
        StringBuilder condition = new StringBuilder();
        String[] genders = (String[]) request.getParameterValues("gender");
        String vse_pohlavi = (String) request.getParameter("vse_pohlavi");
        if (genders != null && genders.length > 0 && (vse_pohlavi == null || vse_pohlavi.isEmpty())){
            condition.append(" and (");
            boolean first = true;
            for (String gender : genders) {
                if (first)
                    first = false;
                else
                    condition.append(" or ");
                condition.append("sex = '").append(gender).append("'");
            }
            condition.append(")");
            
            //do jsp stranky pro zobrazeni aktualniho nastaveni filtru
            Map<String,Boolean> genderMap = new HashMap<String,Boolean>();
            for (String gender : genders) {
                genderMap.put(gender, true);
            }
            request.setAttribute("genderMap", genderMap);
        }
        request.setAttribute("vse_pohlavi", vse_pohlavi);
        
        // podminka skupiny pratel
        String[] fLists = (String[]) request.getParameterValues("friendLists");
        String vse_skupiny = (String) request.getParameter("vse_skupiny");
        if (fLists != null && fLists.length > 0 && (vse_skupiny == null || vse_skupiny.isEmpty())){
            condition.append(" and (");
            boolean first = true;
            for (String fList : fLists) {
                if (first)
                    first = false;
                else
                    condition.append(" or ");
                condition.append("uid IN (SELECT uid FROM friendlist_member WHERE flid = '").append(fList).append("')");
            }
            condition.append(")");
            
            //do jsp stranky pro zobrazeni aktualniho nastaveni filtru
            Map<String,Boolean> fListMap = new HashMap<String,Boolean>();
            for (String fList : fLists) {
                fListMap.put(fList, true);
            }
            request.setAttribute("fListMap", fListMap);
        }
        request.setAttribute("vse_skupiny", vse_skupiny);
        
        System.out.println("condition "+condition);
                
        // ziskani informaci o pratelych
        String uidFriendPar = (String) request.getParameter("uidFriend");
        if (uidFriendPar != null && !uidFriendPar.isEmpty()){
            System.out.println("setUidFriendPar ");
            if (uidFriendPar.equals("smaz")){
                uidFriend = null;
                System.out.println("setUidFriendPar null");
            } else {
                uidFriend = uidFriendPar;
                System.out.println("setUidFriendPar "+uidFriendPar);
            }
               
        }
        List<Friend> friends;
        String omezeni = "Všichni";
         if (uidFriend == null || uidFriend.isEmpty()){
                 // ziskani informaci o pratelych
                friends = fbClient.executeFqlQuery("SELECT uid, name, sex, birthday_date, birthday FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me()) "+condition.toString(), Friend.class);
              
         } else {
           // ziskani informaci o pratelych omezeno
           friends = fbClient.executeFqlQuery("SELECT uid, name, sex, birthday_date, birthday FROM user WHERE uid="+uidFriend+" or uid IN (SELECT uid2 FROM friend WHERE uid1 = "+uidFriend+" and uid2 IN ( SELECT uid2 FROM friend WHERE uid1 = me()))  "+condition.toString(), Friend.class);
           omezeni = fbClient.executeFqlQuery("SELECT name FROM user WHERE uid="+uidFriend, Friend.class).get(0).getName();         
        }
        
        // podminka veku nelze dat do dotazu, je to string a FQL ma omezene moznosti
        String ageRange = (String) request.getParameter("ageRange");
        String vse_vek = (String) request.getParameter("vse_vek");
        request.setAttribute("vse_vek", vse_vek);
        
        String ageFrom = "";
        String ageTo = "";
        if (ageRange != null && ageRange.length() > 0 && (vse_vek == null || vse_vek.isEmpty())){
            System.out.println("ageRange is not null "+ageRange);
            Pattern pattern = Pattern.compile("(\\d\\d) - (\\d\\d)");
            Matcher matcher = pattern.matcher(ageRange);
            if (matcher.find()) {
                ageFrom = matcher.group(1);
                ageTo = matcher.group(2);
                int ageFromI = Integer.valueOf(ageFrom);
                int ageToI = Integer.valueOf(ageTo);
                List<Friend> friendsTemp = new ArrayList<Friend>();
                for (Friend friend : friends) {
                    if (friend.getAge() >= ageFromI && friend.getAge() <= ageToI)
                        friendsTemp.add(friend);
                }
                friends = friendsTemp;
                
                //do jsp stranky pro zobrazeni aktualniho nastaveni filtru
                request.setAttribute("ageFrom", ageFrom);
                request.setAttribute("ageTo", ageTo);
            } else {
                System.out.println("Match not found");
            }
        }
        
        //nastaveni sirky vysky grafu z filtru
        String graphW = (String) request.getParameter("graphWidth");
        String graphH = (String) request.getParameter("graphHeight");
                System.out.println("graphWidth "+graphW);
        if (graphW != null && !graphW.isEmpty() && graphH!=null && !graphH.isEmpty()){
                System.out.println("setGraphWidth ");
            setGraphWidth(Integer.valueOf(graphW));
            setGraphHeight(Integer.valueOf(graphH));
        }
        
        // ziskani vsech skupin pratel do filtru
        List<FriendList> friendLists = fbClient.executeFqlQuery("SELECT flid, name, type FROM friendlist WHERE owner = me()", FriendList.class);

        
        
        // ziskani informaci o prihlasenem uzivateleli
        CurrentUser user = fbClient.fetchObject("/me", CurrentUser.class);

        
        List<Friendship> friendshipsAll = new ArrayList();     

         
        // ziskani pratelskych vztahu mezi prateli
        if (uidFriend == null || uidFriend.isEmpty()){
            for (int i = 0; i < 10; i++) {
                friendshipsAll.addAll( fbClient.executeFqlQuery("SELECT uid1, uid2 FROM friend WHERE uid1 IN (SELECT uid2 FROM friend WHERE substr(uid2,strlen(uid2)-1 ,1)=\""+i+"\" and uid1 = me()) AND uid2 IN (SELECT uid2 FROM friend WHERE uid1 = me())", Friendship.class));    
            }
         } else {
            friendshipsAll = fbClient.executeFqlQuery("SELECT uid1, uid2 FROM friend WHERE uid1 IN (SELECT uid2 FROM friend WHERE uid1="+uidFriend+" and uid2 in (SELECT uid2 FROM friend WHERE uid1 = me())) AND uid2 IN (SELECT uid2 FROM friend WHERE uid1 = me()) ", Friendship.class);    
        }
       
        
        
        System.out.println("pocet vazeb "+friendshipsAll.size());
        
        
       int avgAge = 0;
       int countAge = 0;
        // vytvoreni mapy pratel podle id
        HashMap<String, Friend> fMap = new HashMap<>();
        for (Friend friend : friends) {
            fMap.put(friend.getUid(), friend);
            avgAge += friend.getAge();
            if (friend.getAge()>0)
               countAge++; 
        }
        if (countAge>0)
            avgAge /= countAge;
        else avgAge = 0;
        // vztahy pratel, ktere nevykresluji, zahodim
        List<Friendship> friendships = new ArrayList<>();
        for (Friendship friendship : friendshipsAll) {
            if (fMap.containsKey(friendship.getUid1()) && fMap.containsKey(friendship.getUid2())){
                if (!friendships.contains(friendship))
                    friendships.add(friendship); 
            } 
        }
        System.out.println("pocet vazeb final "+friendships.size());
        // rozmisteni pratel po plose
        int newHeight = Friend.setFriendsPositions(friends, getGraphWidth(), getGraphHeight());
        setGraphHeight(newHeight);

        // predani dat JSP strance, a jeji zobrazeni
        List<Friend> allFriends = fbClient.executeFqlQuery("SELECT uid, name, sex, birthday_date, birthday FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me()) "+condition.toString() +" order by name", Friend.class);
        
        request.setAttribute("omezeni", omezeni);
        request.setAttribute("user", user);
        request.setAttribute("friends", friends);
        request.setAttribute("allFriends", allFriends);
        request.setAttribute("avgAge", avgAge);
        request.setAttribute("friendLists", friendLists);
        // pro vykresleni vytahu
        request.setAttribute("fMap", fMap);
        request.setAttribute("friendships", friendships);
        // sirka vyska obdelniku
        request.setAttribute("rectangleHeight", fb.vis.types.Friend.HEIGHT);
        request.setAttribute("rectangleWidth", fb.vis.types.Friend.WIDTH);
        // sirka vyska grafu
        request.setAttribute("graphWidth", getGraphWidth());
        request.setAttribute("graphHeight", getGraphHeight());
        
        
        request.getRequestDispatcher(FRIENDS_JSP).forward(request, response);
    }

    
    
    public int getGraphHeight() {
        return graphHeight;
    }

    public void setGraphHeight(int graphHeight) {
        this.graphHeight = graphHeight;
    }

    public int getGraphWidth() {
        return graphWidth;
    }

    public void setGraphWidth(int graphWidth) {
        this.graphWidth = graphWidth;
    }

    
}
